package pers.sen.health.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import pers.sen.health.security.JWTAuthenticationFilter;
import pers.sen.health.security.JWTAuthorizationFilter;
import pers.sen.health.security.JWTProperties;
import pers.sen.health.security.MyUserDetailsServiceImpl;

/**
 * @author Jason
 * @version 1.0.0
 * @date 2020/11/13 19:29
 * @Description TODO
 */
@Configuration
// 启动注解权限扫描
@EnableGlobalMethodSecurity(prePostEnabled = true)
// 使自定义配置类生效
@EnableConfigurationProperties(JWTProperties.class)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // 数据库版注入数据库查询封装对象 UserDetailsService或其实现类MyUserDetailsServiceImpl
    @Autowired
    private MyUserDetailsServiceImpl userDetailsService;

    // 注入jwt需要公钥和私钥 配置类
    @Autowired
    private JWTProperties properties;

    /**
     * 在配置类中：先注入 PasswordEncoder对象，用来给密码加密
     *
     * @return
     */
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        // 给密码加密的对象
        return new BCryptPasswordEncoder();
    }

    /**
     * 用户权限认证/授权配置
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 基于内存  定义认证用户的账号 、密码 、以及权限/角色关键字（可以通过注解使用对应的关键字开启权限）
        // 这里的密码是密文验证，所以需要{noop}指明不需要密文验证
//        auth.inMemoryAuthentication().withUser("admin").password("{noop}1234").roles("ADMIN")
//                .and()
//                // 可以使用and()拼接多个用户认证信息
//                .withUser("add").password("{noop}1234").roles("ADD")
//                // 给明文密码加密：security会使用加密bean对前端输入的密码加密和此密码比较
//                .and()
//                // 指定给前端提交密码加密的加密bean
//                .passwordEncoder(passwordEncoder())
//                // 加密后与password进行比对认证
//                .withUser("admin1").password("$2a$10$piCMTRruUqdl3p0qJje0FuJtFqvEEgwyQ5LZzOmcH.fRIzFYooRve").roles("ADMIN");
//        System.out.println("password-1234: "+passwordEncoder().encode("1234"));
        // 数据库版权限认证
        // 传入模板
        auth.userDetailsService(userDetailsService)
                // 传入加密器
                .passwordEncoder(passwordEncoder());


    }

    /**
     * 开放静态资源，无登录也可以访问的资源
     *
     * @param web
     * @throws Exception
     */
//    @Override
//    public void configure(WebSecurity web) throws Exception {
//        // 访问登录界面不需要登录
//        web.ignoring().antMatchers("/template/**",
//                // 开放登录界面
//                "/login.html");
//    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 定义当需要用户登录时候，转到的登录页面。
        // 设置登录页面
//        http.formLogin()
//                .loginPage("/login.html")
//                // 表单提交的action 地址：默认/login可以不写
//                .loginProcessingUrl("/login.do")
//                // 修改表单提交的用户名/密码name属性
//                .usernameParameter("name")
//                .passwordParameter("pwd")
//                // 登录成功之后，默认跳转的页面，true: 每次登陆成功都跳转到index
//                .defaultSuccessUrl("/pages/index.html", true)
//                // 登录失败跳转的页面
//                .failureUrl("/login.html")
//
//                .and()
//                // 请求权限认证
//                .authorizeRequests()
//                // /pages/index.html需要登录且有ADMIN角色才能访问
////                .antMatchers("/pages/index.html").hasRole("ROLE_ADMIN")
//                // /pages/**需要登录才能访问
//                .antMatchers("/pages/**").authenticated()
//
//                .and()
//                // 异常处理页面（403无权限异常）
//                .exceptionHandling().accessDeniedPage("/error.html")
//
//                .and()
//                // 退出登录
//                .logout()
//                // 退出的action，退出后跳转的界面
//                .logoutUrl("/logout.do").logoutSuccessUrl("/login.html")
//                // 清除用户的登录信息，使认证失效
//                .invalidateHttpSession(true)
//
//                .and()
//                // 禁用csrf过滤器（token认证）
//                .csrf().disable();

        http.csrf().
                disable() // crsf   禁用
                // 启用自定义认证过滤器
                .addFilter(new JWTAuthenticationFilter(super.authenticationManager(),properties))
                // 启用自定义鉴权过滤器（获取token中的权限）
                .addFilter(new JWTAuthorizationFilter(super.authenticationManager(),properties))
                .sessionManagement()
                // 禁用session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
}
